﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ProgressWindow.xaml.cs" company="Geologische Bundesanstalt">
//   Thomas Heuberger, 2014-02
// </copyright>
// <summary>
//   Interaction logic for ProgressWindow.xaml
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace AttachmentHandler {
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Windows;

    using Outlook = Microsoft.Office.Interop.Outlook;

    /// <summary>
    /// Interaction logic for ProgressWindow.xaml
    /// </summary>
    public partial class ProgressWindow : Window {
        /// <summary>
        /// The outlook folder.
        /// </summary>
        private List<Outlook.MailItem> mailItems;

        /// <summary>
        /// Initializes a new instance of the <see cref="ProgressWindow"/> class.
        /// </summary>
        /// <param name="mailItems">
        /// The mail items.
        /// </param>
        public ProgressWindow(List<Outlook.MailItem> mailItems) {
            this.mailItems = mailItems;
            this.InitializeComponent();

            this.CloseButton.IsEnabled = false;
            this.SaveProgressBar.Value = 0;
        }

        /// <summary>
        /// The window_ loaded event handler.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private async void Window_Loaded(object sender, RoutedEventArgs e) {
            // new instance of Progress<T>, passing ReportProgress as the Action<T> 
            var progressIndicator = new Progress<string>(this.ReportProgress);

            this.SaveProgressBar.Maximum = this.mailItems.Count;
            
            // run the SaveAttachments method asynchronously
            await this.SaveAttachments(progressIndicator);

            this.CloseButton.IsEnabled = true;
        }

        /// <summary>
        /// The report progress handler.
        /// </summary>
        /// <param name="value">
        /// The value.
        /// </param>
        private void ReportProgress(string value) {
            // this is an internal message when a mail has been processed. increment progress bar.
            if (value.Equals("Processed Mail")) 
                this.SaveProgressBar.Value += 1;
            else this.ProgressTextBox.Text += value;
        }

        /// <summary>
        /// The save attachments method.
        /// </summary>
        /// <param name="progress">
        /// The progress.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        private async Task<int> SaveAttachments(IProgress<string> progress) {
            // get a list of path characters that are invalid on this system.
            var invalid = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());

            var message = "Total number of mails to be processed: " + this.mailItems.Count;
            progress.Report(message + Environment.NewLine + new string('-', message.Length) + Environment.NewLine);

            // spool up a new thread and process the attachments
            await Task.Run(() => {
                    foreach (var thisItem in mailItems) {
                        try {
                            var markAsRead = false;

                            // repalce the subject's invalid characters
                            var subject = thisItem.Subject ?? "No Subject";

                            subject = invalid.Aggregate(subject, (current, c) => current.Replace(c.ToString(), string.Empty));

                            // remove whitespaces
                            subject = subject.Trim();

                            // get the list of non-inline attachments
                            var attachments = Utilities.GetMailAttachments(thisItem);

                            if (attachments.Count > 0)
                                progress.Report(string.Format("Found {0} attachment(s)!" + Environment.NewLine, attachments.Count));

                            // save every attchment
                            foreach (var attachment in attachments) {
                                // append the subject to the destination path
                                var destPath = Path.Combine(Globals.ThisAddIn.Settings.DestinationFolder, subject);
                                try {
                                    // create the path if it doesn't exist
                                    Directory.CreateDirectory(destPath);
                                    attachment.SaveAsFile(Path.Combine(destPath, attachment.FileName));
                                    
                                    // if MarkAsRead is set, mark the mail as read
                                    if (Globals.ThisAddIn.Settings.MarkAsRead)
                                        markAsRead = true;
                                    progress.Report(string.Format("Saved file \"{0}\" to \"{1}\"" + Environment.NewLine, attachment.FileName, destPath + @"\"));
                                } catch (Exception exception) {
                                    progress.Report(string.Format("Error saving file \"{0}\" to \"{1}\". The error was \"{2}\"" + Environment.NewLine, attachment.FileName, destPath, exception.Message));
                                }
                            }

                            if (markAsRead) {
                                thisItem.UnRead = false;
                                progress.Report("Mail marked as read" + Environment.NewLine + "*******************" + Environment.NewLine);
                            }

                            progress.Report("Processed Mail");
                        }
                        catch (Exception exception) {
                            progress.Report(string.Format("There was an error processing the mails. The error was \"{0}\"" + Environment.NewLine, exception.Message));
                        }                                                   
                    }
                });

            progress.Report("Done processing mails!");
            return 0;
        }

        /// <summary>
        /// The close button click handler.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void CloseButtonClick(object sender, RoutedEventArgs e) {
            this.Close();
        }
    }
}
